//Copyright 2008 Kristian Gundry And Rune Juhl-Petersen
//This file is part of Plain.

//Plain is free software: you can redistribute it and/or modify
//it under the terms of the GNU Lesser General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//any later version.

//Plain is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU Lesser General Public License for more details.

//You should have received a copy of the GNU Lesser General Public License
//along with Plain.  If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;

using System.Text;
using System.Collections;
using System.Linq;

namespace Plain.Utilities{
    public static class CollectionExtensions {
        /// <summary>
        /// Copies the content of the list to an array and returns it
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static T[] ToArray<T>(this IList<T> list) {
            T[] array = new T[list.Count];
            list.CopyTo(array,0);
            return array;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="list">
        /// A <see cref="IEnumerable<System.String>"/>
        /// </param>
        /// <param name="delimiter">
        /// A <see cref="System.String"/>
        /// </param>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        /// 
        public static string Concat(this IEnumerable<string> list, string delimiter){
        	return String.Join(delimiter, list.ToArray());
        }
        
        public static string Concat<T>(this IEnumerable<T> list, string delimiter){
        	IList<string> s = new List<string>();
        	foreach(T o in list){
        		s.Add(o.ToString());
        	}
			
        	return string.Join(delimiter,s.ToArray());
        }
		public static string Concat<T>(this IEnumerable<T> list, Func<T,string> func){
			StringBuilder sb = new StringBuilder();
			list.Do(x=>sb.Append(func.Invoke(x)));
			return list.ToString();
		}
		public static string Concat<T>(this IEnumerable<T> list, Func<T,string> func,string delimiter){
			
			IList<string> s = new List<string>();
			list.Do(x=>s.Add(func.Invoke(x)));
			//string.Join( list.Do<T,string>(x=>func.Invoke(x));
			return string.Join(delimiter, s.ToArray());
		}
        public static string Concat<T>(this IEnumerable list, string delimiter) {
            IList<string> s = new List<string>();
            foreach (T o in list) {
                s.Add(o.ToString());
            }
            return string.Join(delimiter,s.ToArray());
        }
        /// <summary>
        /// Returns a multidimentional array
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        public static T[][] ToArray<T>(this IDictionary<T, T> dic) {
            T[][] array = new T[dic.Count][];
            int c = 0;
            foreach(KeyValuePair<T,T> pair in dic){
                array[c++] = new T[2] { pair.Key, pair.Value };
            }
            return array;
        }
        /// <summary>
        ///Performs an action on each element in the collection  
        /// </summary>
        /// <param name="list">
        /// A <see cref="IEnumerable<T>"/>
        /// </param>
        /// <param name="action">
        /// A <see cref="Action<T>"/> lambda to be preformed on each element
        /// </param>
        public static void Do<T>(this IEnumerable<T> list,Action<T> action){
            if (list != null) {
                foreach (T t in list) {
                    action.Invoke(t);
                }
            }
        }
        public static IEnumerable<TResult> Do<T,TResult>(this IEnumerable<T> list,Func<T, TResult> func){
        	IList<TResult> results = new List<TResult>();
        	foreach(T t in list){
        		results.Add(func.Invoke(t));
        	}
        	return results;
        }
		/// <summary>
		///Returns a collection that is not null. 
		/// </summary>
		/// <param name="input">
		/// A <see cref="IEnumerable<T>"/>
		/// </param>
		/// <returns>
		/// A <see cref="IEnumerable<T>"/>
		/// </returns>
		/// <example>
		/// IList<User> users = null;
		/// foreach(User u in users.NullChecked()){
		/// 	//do stuff
		/// }
		/// </example>
		public static IEnumerable<T> NullChecked<T>(this IEnumerable<T> input){
			if(input!=null){
				return input;
			}else{
				return Enumerable.Empty<T>();//new List<T>();
			}
			
		}
    }
}
